package com.yanqu.road.server.manger;

import com.yanqu.road.dao.impl.config.ForbiddenWordOverSeasDaoImpl;
import com.yanqu.road.entity.forbiddenword.ForbiddenWordOverSeasData;
import com.yanqu.road.logic.redis.RedisKeyDefineHelper;
import com.yanqu.road.logic.redis.RedisManger;
import com.yanqu.road.reids.subpub.eRedisChannelType;
import com.yanqu.road.server.TempMgr;
import com.yanqu.road.utils.ConfigHelper;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class ForbiddenWordOverSeasMgr extends TempMgr {
    private static List<ForbiddenWordOverSeasData> wordDataList = new ArrayList<>();
    private static List<Pattern> wordPatternList = new ArrayList<>();
    private static AtomicInteger wordDataId = new AtomicInteger(1);
    public static final int ONE_LINE_WORD_NUM = 1000; // 一行最多的屏蔽词数量


    @Override
    public boolean init() throws Exception {
        return reload();
    }

    @Override
    public boolean reloadConfig() throws Exception {
        return true;
    }

    @Override
    public boolean reloadData() throws Exception {
        loadDb();
        return true;
    }

    @Override
    public boolean stop() {
        return true;
    }

    @Override
    public boolean save() {
        return true;
    }

    public static boolean saveDb() {
        try {
            List<ForbiddenWordOverSeasData> dataList = getWordDataList();
            for (ForbiddenWordOverSeasData data : dataList) {
                if (data.isInsertOption()) {
                    new ForbiddenWordOverSeasDaoImpl().add(data);
                } else if (data.isUpdateOption()) {
                    new ForbiddenWordOverSeasDaoImpl().update(data);
                }
            }
        } catch (Exception e) {
            getLogger().error("ForbiddenWordOverSeasMgr saveDb error", e);
            return false;
        }

        return true;
    }

    public static void loadDb() {
        getLogger().info("loadDb ForbiddenWordOverSeasMgr start");
        List<ForbiddenWordOverSeasData> tempDataList = new ForbiddenWordOverSeasDaoImpl().getForbiddenWordOverSeasData();
        wordDataList = tempDataList;

        refreshWordPatternList();
        getLogger().info("loadDb ForbiddenWordOverSeasMgr end");
    }

    public static List<ForbiddenWordOverSeasData> getWordDataList() {
        synchronized (wordDataList) {
            return new ArrayList<>(wordDataList);
        }
    }

    public static void addNewWordList(List<String> wordList) {
        if (wordList == null || wordList.isEmpty()) {
            return;
        }

        synchronized (wordDataList) {
            //先往旧数据里塞,塞满1000个单词再新增一条
            //去重
            List<String> addWordList = new ArrayList<>();
            for (String word : wordList) {
                boolean isExist = false;
                for (ForbiddenWordOverSeasData wordOverSeasData : wordDataList) {
                    if (wordOverSeasData.contains(word)) {
                        isExist = true;
                        break;
                    }
                }
                if (!isExist) {
                    addWordList.add(word);
                }
            }

            for (ForbiddenWordOverSeasData wordOverSeasData : wordDataList) {
                if (wordOverSeasData.isFull(ONE_LINE_WORD_NUM)) {
                    continue;
                }

                int addNum = ONE_LINE_WORD_NUM - wordOverSeasData.getWordSet().size();
                for (int i = 0; i < addNum; i++) {
                    if (addWordList.isEmpty()) {
                        break;
                    }
                    String word = addWordList.remove(0);
                    wordOverSeasData.addWord(word);
                    if (addWordList.isEmpty()) {
                        break;
                    }
                }
            }

            while (!addWordList.isEmpty()) {
                ForbiddenWordOverSeasData wordOverSeasData = new ForbiddenWordOverSeasData(wordDataId.getAndIncrement());
                for (int i = 0; i < ONE_LINE_WORD_NUM; i++) {
                    String word = addWordList.remove(0);
                    wordOverSeasData.addWord(word);
                    if (addWordList.isEmpty()) {
                        break;
                    }
                }
                wordDataList.add(wordOverSeasData);
            }
        }

        getLogger().info("addNewWordList ForbiddenWordOverSeasMgr wordDataList size:{}", wordDataList.size());
        if (saveDb()) {
            publishRedis();
        }
    }

    public static void publishRedis() {
        getLogger().info("publishRedis ForbiddenWordOverSeasMgr start");
        Long count = RedisManger.getRedisUtil().publish(eRedisChannelType.SystemConfig.getChannel(), RedisKeyDefineHelper.getForbiddenWordPublishMsg());
        getLogger().info("publishRedis ForbiddenWordOverSeasMgr count:{}", count);
    }

    public static void removeWordList(List<String> wordList) {
        if (wordList == null || wordList.isEmpty()) {
            return;
        }

        List<String> removeWordList = new ArrayList<>(wordList);
        synchronized (wordDataList) {
            while (!removeWordList.isEmpty()) {
                String removeWord = removeWordList.remove(0);

                for (ForbiddenWordOverSeasData wordOverSeasData : wordDataList) {
                    if (wordOverSeasData.removeWord(removeWord)) {
                        break;
                    }
                }
            }
        }

        getLogger().info("removeWordList ForbiddenWordOverSeasMgr wordDataList size:{}", wordDataList.size());
        if (saveDb()) {
            publishRedis();
        }
    }

    public static void refreshWordPatternList() {
        List<ForbiddenWordOverSeasData> dataList = getWordDataList();

        List<Pattern> patternList = new ArrayList<>();
        for (ForbiddenWordOverSeasData wordOverSeasData : dataList) {
            for (String word : wordOverSeasData.getWordSet()) {
                word = word.toLowerCase();
                patternList.add(Pattern.compile(ForbiddenWordMgr.translateWord(word)));
            }
        }
        wordPatternList = patternList;
    }

    public static boolean isForbidden(String word) {
        for (Pattern pattern : wordPatternList) {
            Matcher matcher = pattern.matcher(word);
            if (matcher.matches()) {
                return true;
            }
        }
        return false;
    }
}
